Подтвердить что ты не робот

Кэширование вывода для ApiController (MVC4 Web API)

Я пытаюсь кэшировать вывод ApiController в веб-API.

Здесь код контроллера:

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

N.B. Я также попробовал атрибут OutputCache на самом контроллере, а также несколько комбинаций его параметров.

Маршрут зарегистрирован в Global.asax:

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

Я получаю успешный ответ, но он не кэшируется нигде:

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>

Мне не удалось найти документацию для кэширования вывода в веб-API.

Является ли это ограничением веб-API в MVC4, или я делаю что-то неправильно?

4b9b3361

Ответ 1

WebAPI не имеет встроенной поддержки атрибута OutputCache. Возьмите обзор этой статьи, чтобы узнать, как вы можете реализовать эту функцию самостоятельно.

Ответ 2

В ответе Aliostad говорится, что веб-API отключает кеширование, а код HttpControllerHandler показывает, что он выполняет WHEN response.Headers.CacheControl - null.

Чтобы ваш пример ApiController Action возвращал результат кэширования, вы можете:

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

и вы получите заголовок ответа HTTP следующим образом:

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

Ответ 3

В течение последних нескольких месяцев я работал над кешированием HTTP для веб-API ASP.NET. Я внес вклад в WebApiContrib для серверной части, и соответствующую информацию можно найти на моем blog.

Недавно я начал расширять работу и добавлять клиентскую сторону, а также в библиотеку CacheCow. Первые пакеты NuGet были выпущены сейчас (благодаря Tugberk). Вскоре я напишу сообщение в блоге. Поэтому следите за пространством.


Но для ответа на ваш вопрос ASP.NET Web API по умолчанию отключает кеширование. Если вы хотите, чтобы ответ был кэширован, вам нужно добавить заголовок CacheControl в ответ в своем контроллере (и на самом деле лучше быть в обработчике делегирования, подобном CachingHandler в CacheCow).

Этот фрагмент от HttpControllerHandler в исходном коде 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);
        }

Ответ 4

Вы можете использовать это на регулярном MVC-контроллере:

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

но атрибут OutputCache находится в пространстве имен System.Web.Mvc и недоступен в ApiController.