C# ApiController 的输出缓存(MVC4 Web API)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11547618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 18:13:37  来源:igfitidea点击:

Output caching for an ApiController (MVC4 Web API)

c#asp.net-web-apioutputcachehttp-caching

提问by Samu Lang

I'm trying to cache the output of an ApiControllermethod in Web API.

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

Here's the controller code:

这是控制器代码:

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

N.B. I'd also tried the OutputCache attribute on the controller itself, as well as several combinations of its parameters.

注意,我还尝试了控制器本身的 OutputCache 属性,以及其参数的几种组合。

The route is registered in Global.asax:

该路由在 Global.asax 中注册:

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

I get a successful response, but it's not cached anywhere:

我得到了成功的响应,但它没有缓存在任何地方:

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>

I was not able to find documentation for output caching in Web API.

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

Is this a limitation of the Web API in MVC4 or am I doing something wrong?

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

采纳答案by Cory

WebAPI does not have any built in support for the [OutputCache]attribute. Take a look at this articleto see how you could implement this feature yourself.

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

回答by Aliostad

For the last few months, I have been working on HTTP caching for ASP.NET Web API. I have contributed to WebApiContribfor server-side and relevant information can be found on my blog.

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

Recently I have started to expand the work and add the client-side as well in the CacheCowlibrary. First NuGet packages have been released now (thanks to Tugberk) More to come. I will write a blog post soon on this. So watch the space.

最近我开始扩展工作并在CacheCow库中添加客户端。现在已经发布了第一个 NuGet 包(感谢Tugberk)更多。我很快会写一篇关于这个的博客文章。所以看空间。



But in order to answer your question, ASP.NET Web API by default turns off the caching. If you want the response to be cached, you need to add the CacheControl header to the response in your controller (and in fact better be in a delegating handler similar to CachingHandler in CacheCow).

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

This snippet is from HttpControllerHandlerin ASP.NET Web Stack source code:

此代码段来自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);
        }

回答by broxten

You could use this on a regular MVC Controller:

您可以在常规 MVC 控制器上使用它:

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

but OutputCache attribute is in System.Web.Mvc namespace and not available in an ApiController.

但是 OutputCache 属性在 System.Web.Mvc 命名空间中,在 ApiController 中不可用。

回答by Luciano Carvalho

The answer of Aliostad states that Web API turns off caching, and the code of HttpControllerHandler shows that it does WHEN response.Headers.CacheControl is null.

Aliostad 的回答说Web API 关闭缓存,HttpControllerHandler 的代码显示它在 WHEN response.Headers.CacheControl 为null 时关闭。

To make your example ApiController Action return a cacheable result, you can:

要使您的示例 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;
    }
}

and you will get a HTTP response header like this:

你会得到一个像这样的 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
...

回答by himanshupareek66

I am very late, but still thought to post this great article on Caching in WebApi

我很晚了,但仍然想发表这篇关于 WebApi 缓存的好文章

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

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

In the above code, we have overridden OnActionExecuted method and set the required header in the response. Now I have decorated the Web API call as

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

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