Reputation: 4339
To reproduce the issue: using Visual Studio 2015, create an Asp.Net framework web app with MVC and Web API. Create an Example
api controller like this:
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");
}
}
And that's it. Run the app and check the dev tools in Chrome and the Cache-Control header is still just it's default value:
If I change the above code to
HttpContext.Current.Response.AppendHeader("foobar", "no-cache, no-store, must-validate");
It actually does set the header:
I can't find anything about this on google. I've tried the action filter attribute approach to setting the headers and it appears to be the exact same issue.
How do I override the default Cache-Control header in Asp.Net Web API?
Edit: I'm not sure what's wrong with the above, but if I replace with an action filter I can get it to work, except only if it's a synchronous controller method:
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);
}
}
That works with synchronous controller actions but not an async
like this
[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);
}
}
How do I get it to work with async
?
Upvotes: 4
Views: 1884
Reputation: 394
I think in your action method you are overrididng CacheControl headers by using OK("foo") after you set cache control headers, instead you should flip your code and set Cache Control afterwards.
Also, in you Action attribute
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)
};
}
}
Upvotes: 1
Reputation: 10697
Your CacheControlAttribute
looks decent to me, not sure why it doesn't work. I was looking for less custom solutions, and what really helped me is enforcing the no cache directives by the RegisterGlobalFilters
of App_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
});
}
}
Upvotes: 0