【问题标题】:Why can't I set Cache-Control header in Web API2为什么我不能在 Web API2 中设置 Cache-Control 标头
【发布时间】:2018-11-22 06:28:39
【问题描述】:

要重现该问题:使用 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 标头仍然只是它的默认值:

如果我把上面的代码改成

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

它确实设置了标题:

我在 google 上找不到任何关于此的信息。我已经尝试过设置标题的操作过滤器属性方法,它似乎是完全相同的问题。

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

编辑:我不确定上面有什么问题,但如果我用动作过滤器替换,我可以让它工作,除非它是一个同步控制器方法:

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 一起使用?

【问题讨论】:

  • 你找到问题了吗?我有完全一样的问题。我想为一个 API 函数打开缓存。 Response.Headers.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue { MaxAge = TimeSpan.FromSeconds(Duration), Public = true, MustRevalidate = true };但在 WebApiApplication_EndRequest(和浏览器)中,会出现原始缓存标头。

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


【解决方案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)
        };
    }
}

【讨论】:

    【解决方案2】:

    您的CacheControlAttribute 对我来说看起来不错,不知道为什么它不起作用。我一直在寻找较少定制的解决方案,真正帮助我的是通过RegisterGlobalFiltersApp_Start/FilterConfig.cs 执行无缓存指令:

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            // ...
            filters.Add(new OutputCacheAttribute
            {
                NoStore = true,
                Duration = 0,
                VaryByParam = "*",
                Location = System.Web.UI.OutputCacheLocation.None
            });
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-27
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 2019-01-20
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多