为什么我不能在Web API2中设置Cache-Control标头

时间:2018-06-12 19:12:08

标签: asp.net-mvc asp.net-web-api asp.net-web-api2 cache-control

重现此问题:使用Visual Studio 2015,使用MVC和Web API创建Asp.Net框架Web应用程序。像这样创建一个Example api控制器:

using System.Web;
using System.Web.Http;
public class ExampleController : ApiController
{
    public IHttpActionResult Get()
    {
        HttpContext.Current.Response.AppendHeader("Cache-Control", "no-cache, no-store, must-validate");
        return Ok("foo");
    }
}

就是这样。运行该应用并检查Chrome中的开发工具,Cache-Control标头仍然是它的默认值:

Cache-Control is set to default value instead of what was specified in Web Api controller method

如果我将上述代码更改为

HttpContext.Current.Response.AppendHeader("foobar", "no-cache, no-store, must-validate");

它确实设置了标题:

It does add the foobar header

我无法在谷歌上找到任何相关信息。我已尝试使用操作过滤器属性方法来设置标头,但它似乎是完全相同的问题。

如何覆盖Asp.Net Web API中的默认Cache-Control标头?

修改:我不确定上述内容有什么问题,但如果我更换动作过滤器,我可以让它起作用,除非它只是&#39 ; sa同步控制器方法:

using System;
using System.Web.Http.Filters;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
public class CacheControlAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext context)
    {
        if (context.Response != null)
        {
            context.Response.Headers.CacheControl = new CacheControlHeaderValue()
            {
                NoStore = true,
                NoCache = true,
                MustRevalidate = true,
                MaxAge = new TimeSpan(0)
            };
        }
        base.OnActionExecuted(context);
    }
    public override async Task OnActionExecutedAsync(HttpActionExecutedContext context, CancellationToken cancellationToken)
    {
        if (context.Response != null)
        {
            context.Response.Headers.CacheControl = new CacheControlHeaderValue()
            {
                NoStore = true,
                NoCache = true,
                MustRevalidate = true,
                MaxAge = new TimeSpan(0)
            };
        }
        await base.OnActionExecutedAsync(context, cancellationToken);
    }
}

适用于同步控制器操作,但不适用于此类async

    [CacheControl]
    public async Task<IHttpActionResult> Get()
    {
        using(Model1 db=new Model1())
        {
            var result =await db.MyEntities.Where(n => n.Name == "foo").SingleOrDefaultAsync();
        return Ok(result);
        }
    }

如何让它与async一起使用?

2 个答案:

答案 0 :(得分:1)

我认为在您的操作方法中,设置缓存控制标头后,您可以通过使用OK(“ foo”)覆盖CacheControl标头,而应该翻转代码并随后设置缓存控制。

此外,在您的Action属性中

public override async Task OnActionExecutedAsync(HttpActionExecutedContext context, CancellationToken cancellationToken)
{
    await base.OnActionExecutedAsync(context, cancellationToken);
    if (context.Response != null)
    {
        context.Response.Headers.CacheControl = new CacheControlHeaderValue()
        {
            NoStore = true,
            NoCache = true,
            MustRevalidate = true,
            MaxAge = new TimeSpan(0)
        };
    }
}

答案 1 :(得分:0)

您的CacheControlAttribute在我看来不错,不确定为什么不起作用。我一直在寻找较少的自定义解决方案,而真正帮助我的是通过RegisterGlobalFilters的{​​{1}}来执行no cache指令:

App_Start/FilterConfig.cs