在Web API中设置HTTP缓存控制头

58
什么是在WebAPI中设置缓存控制标头以供公共缓存服务器使用的最佳方法?
我不关心在我的服务器上的OutputCache控制,我想在CDN端和之后控制缓存(我有单独的API调用,其中响应可以无限期地缓存给定的URL),但到目前为止,我所读到的所有内容要么涉及WebAPI的预发布版本(因此引用似乎已不存在的东西,如System.Web.HttpContext.Current.Response.Headers.CacheControl),要么对于仅设置几个http标头而言似乎非常复杂。
是否有简单的方法来实现这一点?
4个回答

103

如评论中所建议,您可以创建一个ActionFilterAttribute。这是一个简单的过滤器,只处理MaxAge属性:

public class CacheControlAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    public int MaxAge { get; set; }

    public CacheControlAttribute()
    {
        MaxAge = 3600;
    }

    public override void OnActionExecuted(HttpActionExecutedContext context)
    {
        if (context.Response != null)
            context.Response.Headers.CacheControl = new CacheControlHeaderValue()
            {
                Public = true,
                MaxAge = TimeSpan.FromSeconds(MaxAge)
            };

        base.OnActionExecuted(context);
    }
}

那么你可以将其应用于你的方法中:

 [CacheControl(MaxAge = 60)]
 public string GetFoo(int id)
 {
    // ...
 }

这个缓存只适用于客户端吗?对于服务器缓存,我应该将Strathweb.CacheOutput.WebApi2属性设置为任何值,是吗? - Lucas Roselli

81

缓存控制头可以这样设置。

public HttpResponseMessage GetFoo(int id)
{
    var foo = _FooRepository.GetFoo(id);
    var response = Request.CreateResponse(HttpStatusCode.OK, foo);
    response.Headers.CacheControl = new CacheControlHeaderValue()
        {
            Public = true,
            MaxAge = new TimeSpan(1, 0, 0, 0)
        };
    return response;
}

7
这是我所知道的方法之一,但我希望有一种更少侵入性的方法,特别是不需要从方法声明中删除有用信息(从具体的返回类型变为非常通用的类型不是一个很好的改变,我的意见)。无论如何,还是谢谢。 - user32826
3
@Moo,你可以轻松地创建一个ActionFilterAttribute来执行这几行代码。就我个人而言,我仅使用HttpResponseMessage作为我的返回类型,因此上述样式并不困扰我。HTTP是一个通用的接口,因此在我的API层面反映这一点对我来说是有意义的。 - Darrel Miller
3
如果您能根据签名看出是什么内容被发送,我可能会同意。但是,您不知道正在通过网络传输的内容。它可能是JSON格式,也可能是对象的XML序列化或DataContractSerialization序列化。除非您知道所有已安装的格式化程序、它们的设置顺序、接受标头的样式以及格式化程序的限制等信息,否则您无法了解该内容的具体情况。 - Darrel Miller
3
通过电线传输的只是其中一半,我需要编写和维护这些内容,并将其交给其他开发者。将实际返回值隐藏在方法块里而不是在声明中意味着文档必须始终完全准确,我们知道这很难做到。 - user32826
1
@VishnooRath 无论您使用属性路由还是常规路由,它的工作方式都是相同的。 - Darrel Miller
显示剩余4条评论

10

1
你在 duration 后面缺少一个闭合括号 ) :) - Daniel Habenicht

3

我刚在NuGet中找到了它,但我猜那可能是一个VS版本的问题。 - lukkea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接