ApiController的输出缓存(MVC4 Web API)

Sam*_*ang 46 c# outputcache http-caching asp.net-web-api

我正在尝试在Web API中缓存ApiController方法的输出.

这是控制器代码:

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

NB我还尝试了控制器本身的OutputCache属性,以及它的几个参数组合.

该路线在Global.asax中注册:

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

我得到了一个成功的回复,但它没有缓存在任何地方:

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>
Run Code Online (Sandbox Code Playgroud)

我无法在Web API中找到输出缓存的文档.

这是MVC4中Web API的限制还是我做错了什么?

Cor*_*ory 40

WebAPI没有任何内置的[OutputCache]属性支持.采取看看这篇文章,看看你怎么可以自己实现这个功能.

  • 那这个呢?http://www.strathweb.com/2012/05/output-caching-in-asp-net-web-api/ (2认同)

Luc*_*lho 33

Aliostad的答案表明Web API关闭了缓存,而HttpControllerHandler的代码显示它确实在响应时.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

你会得到一个像这样的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
...
Run Code Online (Sandbox Code Playgroud)

  • 这个问题是关于"输出缓存",它是一种特定类型的缓存,其中响应由Web服务器本身缓存.AFAIK这与Cache-Control标头无关. (6认同)
  • 我认为,您在服务器端执行的操作,缓存方式(内存,磁盘,数据库等)以及取决于您的时间长短。如果将项目标记为可缓存和公开,则允许客户端和服务器之间的浏览器服务器和代理服务器(以及其他服务器)自行提供缓存的内容,而不必再次从服务器获取内容。 (2认同)
  • @Tom MVC 输出缓存属性参数被转换为不同的 Cache-Control 标头。请参阅此示例:http://stackoverflow.com/a/20895704/1197771 因此,虽然这个答案没有专门使用“OutputCacheAttribute”,但它确实达到了预期的结果。 (2认同)

Ali*_*tad 15

在过去的几个月里,我一直致力于ASP.NET Web API的HTTP缓存.我为WebApiContrib贡献了服务器端,相关信息可以在我的博客上找到.

最近我开始扩展工作并在CacheCow库中添加客户端.第一批NuGet套餐现已发布(感谢Tugberk)更多内容.我很快就会写一篇博文.所以看空间.


但为了回答您的问题,ASP.NET Web API默认关闭缓存.如果希望缓存响应,则需要将CacheControl标头添加到控制器中的响应中(实际上最好是在类似于CacheCow中的CachingHandler的委托处理程序中).

此代码段来自HttpControllerHandlerASP.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);
        }
Run Code Online (Sandbox Code Playgroud)


him*_*k66 6

我很晚了,但仍然想发表这篇关于 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
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我们重写了 OnActionExecuted 方法并在响应中设置了所需的标头。现在我已将 Web API 调用修饰为

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