我正在使用ASP.NET Core(ASP.NET 5)Web API应用程序,并且必须在实体标签的帮助下实现HTTP缓存.早些时候我使用了CacheCow,但现在似乎不支持ASP.NET Core.我也没有找到任何其他相关的库或框架支持的详细信息.
我可以编写相同的自定义代码,但之前我想看看是否有任何可用的.请分享一些可用的东西,什么是更好的实现方式.
非常感谢.
解决方法
我也有同样的要求,但是
Bennie Wentzel’s anwser还没有完成,因为它仍然返回响应的正文.根据
spec 不应该.
经过一段时间的尝试使其与中间件一起工作,我发现MVC action filters实际上更适合这个功能.
- public class ETagFilter : Attribute,IActionFilter
- {
- private readonly int[] _statusCodes;
- public ETagFilter(params int[] statusCodes)
- {
- _statusCodes = statusCodes;
- if (statusCodes.Length == 0) _statusCodes = new[] {200};
- }
- public void OnActionExecuting(ActionExecutingContext context)
- {
- }
- public void OnActionExecuted(ActionExecutedContext context)
- {
- if (context.HttpContext.Request.Method == "GET")
- {
- if (_statusCodes.Contains(context.HttpContext.Response.StatusCode))
- {
- //I just serialize the result to JSON,could implement IEquality<> for better performance.
- var content = context.Result.ToJson();
- var etag = ETagGenerator.GetETag(context.HttpContext.Request.Path.ToString(),Encoding.UTF8.GetBytes(content));
- if (context.HttpContext.Request.Headers.Keys.Contains("If-None-Match") && context.HttpContext.Request.Headers["If-None-Match"].ToString() == etag)
- {
- context.Result = new StatusCodeResult(304);
- }
- context.HttpContext.Response.Headers.Add("ETag",new[] { etag });
- }
- }
- }
- }
然后将其用作您想要的动作或控制器作为属性:
- [HttpGet]
- [Route("/api/data/")]
- [ETagFilter(200)]
- public async Task<IActionResult> GetDataFromApi()
- {
- ...
- }
这两种方法之间的重要区别在于,您的中间件可以在MVC middlware之前和之后运行,并且只能使用HttpContext.一旦MVC开始将响应发送回客户端,为时已晚,无法进行任何更改.
另一方面,动作过滤器是MVC中间件的一部分.他们可以访问MVC上下文,在这种情况下,实现此功能更为简单. More on Filters及其在MVC中的管道.