Ответ 1
WebAPI не имеет встроенной поддержки атрибута OutputCache. Возьмите обзор этой статьи, чтобы узнать, как вы можете реализовать эту функцию самостоятельно.
Я пытаюсь кэшировать вывод 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, или я делаю что-то неправильно?
WebAPI не имеет встроенной поддержки атрибута OutputCache. Возьмите обзор этой статьи, чтобы узнать, как вы можете реализовать эту функцию самостоятельно.
В ответе 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
...
В течение последних нескольких месяцев я работал над кешированием 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);
}
Вы можете использовать это на регулярном 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.