ASP.NET Core ResponseCache进行缓存操作
前言
本章将介绍客户端缓存将介绍浏览器缓存和服务端缓存,使用浏览器缓存将减少对web服务器的请求次数,同时可以提升性能,避免重复的运算浪费。
ASP.NET Core对于HTTP缓存分为两种:
- 客户端(浏览器缓存)
 - 服务端缓存
 
客户端缓存
通过设置HTTP的响应头 Cache-Control 来完成页面存储到浏览器缓存中如下所示:

其实客户端缓存的话只需要进行设置 ResponseCache 特性就可以请看如下代码片段
[ResponseCache(Duration = 100,Location = ResponseCacheLocation.Client)]
public IActionResult Index()
{
      return View();
}

ResponseCacheAttribute 可应用于:
- Razor 页面处理程序(类) – 特性不能应用于处理程序方法。
 - MVC 控制器(类)。
 - MVC 操作(方法) – 方法级特性覆盖类级特性中指定的设置。
 
[ResponseCache] 参数
- Duration 设置缓存的存储时间(以秒为单位)。设置“Cache-control”中的“max-age”。
 - Location
- Any 缓存在代理和客户端。设置“Cache-control”标题为“public”。
 - Client 只缓存在客户端。设置“Cache-control”标题为“private”。
 - None 每次有请求发出时,缓存会将请求发到服务器 ,服务器端会验证请求中所描述的缓存是否过期,若未过期(注:实际就是返回304),则缓存才使用本地缓存副本。 报头设置为“no-cache”。
 
 - NoStore 缓存中不得存储任何关于客户端请求和服务端响应的内容。每次由客户端发起的请求都会下载完整的响应内容。
 - VaryByHeader 使用vary头有利于内容服务的动态多样性。例如,使用Vary: User-Agent头,缓存服务器需要通过UA判断是否使用缓存的页面。
 - VaryByQueryKeys 可以按照相同页面,不同的参数进行相应的存储
 - CacheProfileName 设置缓存配置文件的值,可以通过设置不同的缓存参数
 
CacheProfileName使用请看如下代码片段
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews(options =>
            {
                options.CacheProfiles.Add("default", new CacheProfile
                {
                    Duration = 60
                });
                options.CacheProfiles.Add("test", new CacheProfile
                {
                    Duration = 30
                });
            });
        }
上述代码我们设置好了两份不一样的配置,那么我们就可以通过下面代码片段进行使用了
    [ResponseCache(CacheProfileName = "default")]
    public IActionResult Index()
    {
         return View();
   }
服务端缓存
服务端缓存可以缓存页面数据和API数据,同时如果我们服务端存在数据,也就是缓存命中的情况下,会直接从缓存中取,不会再进入我们的方法。
        public void ConfigureServices(IServiceCollection services)
        {
              services.AddResponseCaching(options =>
            {
                options.UseCaseSensitivePaths = false;
                options.MaximumBodySize = 1024;
                options.SizeLimit = 100 * 1024*1024;
            });
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseResponseCaching();
        }
服务端缓存配置如下
| 属性 | 描述 | 
|---|---|
| MaximumBodySize | 响应正文的最大可缓存大小(以字节为单位)。 默认值为 64 * 1024 * 1024 (64 MB)。 | 
| SizeLimit | 响应缓存中间件的大小限制(以字节为单位)。 默认值为 100 * 1024 * 1024 (100 MB)。 | 
| UseCaseSensitivePaths | 确定是否将响应缓存在区分大小写的路径上。 默认值是 false。 | 
        [ResponseCache(Duration = 30, VaryByQueryKeys = new[] { "q" })]
        public IActionResult Index(int q)
        {
            _logger.LogWarning($"我是一个路径:{HttpContext.Request.Host}");
            return View(model:DateTime.Now.ToString());
        }
VaryByQueryKeys
使用 MVC/web API 控制器或 Razor Pages 页面模型时, [ResponseCache]属性指定为响应缓存设置适当的标头所需的参数。 严格需要中间件的 [ResponseCache] 属性的唯一参数 VaryByQueryKeys,这与实际 HTTP 标头不对应。 有关详细信息,请参阅 响应缓存在 ASP.NET Core。
如果不使用 [ResponseCache] 属性,响应缓存可能会与 VaryByQueryKeys不同。
我们再看看如上代码效果

ResponseCache中间件使用的 HTTP 标头
| 响应头 | 描述 | 
|---|---|
| Authorization | 如果标头存在,则不会缓存。 | 
| Cache-Control | 中间件仅考虑用 public 缓存指令标记的缓存响应。 | 
| Pragma | 请求中的 Pragma: no-cache 标头将产生与 Cache-Control: no-cache相同的效果。 如果存在此标头,则由 Cache-Control 标头中的相关指令重写。 考虑向后兼容 HTTP/1.0。 | 
| Set-Cookie | 如果标头存在,则不会缓存响应。 请求处理管道中设置一个或多个 cookie 的任何中间件会阻止响应缓存中间件缓存响应(例如,基于 cookie 的 TempData 提供程序)。 | 
| Vary | Vary 标头用于根据另一个标头改变缓存的响应。 例如,通过编码来缓存响应,包括 Vary: Accept-Encoding 响应头,该响应头将缓存标头为 Accept-Encoding: gzip 和 Accept-Encoding: text/plain 的请求的响应。 永远不会存储响应头值为 * 的响应。 | 
| Expires | 除非被其他 Cache-Control 标头重写,否则不会存储或检索此响应头过时的响应。 | 
| If-None-Match | 如果值不为 *,响应的 ETag 与提供的任何值都不匹配,则将从缓存中提供完整响应。 否则,将提供304(未修改)响应。 | 
| If-Modified-Since | 如果 If-None-Match 标头不存在,则在缓存的响应日期比提供的值更新时,将从缓存中提供完整响应。 否则,将提供304-未修改响应 | 
| Date | 从缓存提供时,如果未在原始响应中提供,则中间件会设置 Date 标头。 | 
| Content-Length | 从缓存提供时,如果未在原始响应中提供,则中间件会设置 Content-Length 标头。 | 
| Age | 忽略原始响应中发送的 Age 标头。 中间件在为缓存的响应提供服务时计算一个新值。 | 
缓存条件
- 请求必须导致服务器响应,状态代码为200(正常)。
 - 请求方法必须为 GET 或 HEAD。
 - 在 Startup.Configure中,响应缓存中间件必须置于需要缓存的中间件之前。
 - Authorization 标头不得存在。
 - Cache-Control 标头参数必须是有效的,并且响应必须标记为 "public" 且未标记为 "private"。
 - 如果 Cache-Control 标头不存在,则 Pragma: no-cache 标头不得存在,因为 Cache-Control 标头在存在时将覆盖 Pragma 标头。
 - Set-Cookie 标头不得存在。
 - Vary 标头参数必须有效且不等于 *。
 - Content-Length 标头值(如果已设置)必须与响应正文的大小匹配。
 - 不使用 IHttpSendFileFeature。
 - Expires 标头和 max-age 和 s-maxage 缓存指令指定的响应不能过时。
 - 响应缓冲必须成功。 响应的大小必须小于配置的或默认 SizeLimit。 响应的正文大小必须小于配置的或默认的 MaximumBodySize。
 - "请求" 或 "响应" 标头字段中不得存在 "no-store" 指令。
 
Reference
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching_FAQ
https://docs.microsoft.com/en-us/aspnet/core/performance/caching/middleware?view=aspnetcore-3.1
https://github.com/hueifeng/BlogSample/tree/master/src/ResponseCachingDemo
ASP.NET Core ResponseCache进行缓存操作的更多相关文章
- ASP.NET Core中的缓存[1]:如何在一个ASP.NET Core应用中使用缓存
		
.NET Core针对缓存提供了很好的支持 ,我们不仅可以选择将数据缓存在应用进程自身的内存中,还可以采用分布式的形式将缓存数据存储在一个“中心数据库”中.对于分布式缓存,.NET Core提供了针对 ...
 - asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案
		
之前碰到asp.net core异步进行新增操作并且需要判断某些字段是否重复的问题,进行插入操作的话会导致数据库中插入重复的字段!下面把我的解决方法记录一下,如果对您有所帮助,欢迎拍砖! 场景:EFC ...
 - ASP.NET Core 2.0 MVC 发布部署--------- ASP.NET Core 发布的具体操作
		
ASP.NET Core 发布的具体操作 下面使用C# 编写的ASP.NET Core Web项目示例说明发布的全过程. 1.创建项目 选择“文件” > “新建” > “项目”. 在“添加 ...
 - 使用 Visual Studio 部署 .NET Core 应用 ——ASP.NET Core 发布的具体操作
		
ASP.NET Core 发布的具体操作 下面使用C# 编写的ASP.NET Core Web项目示例说明发布的全过程. 1.创建项目 选择“文件” > “新建” > “项目”. 在“添加 ...
 - C#实现多级子目录Zip压缩解压实例  NET4.6下的UTC时间转换  [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了  asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程  asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案  .NET Core开发日志
		
C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...
 - ASP.Net Core使用分布式缓存Redis从入门到实战演练
		
一.课程介绍 人生苦短,我用.NET Core!缓存在很多情况下需要用到,合理利用缓存可以一方面可以提高程序的响应速度,同时可以减少对特定资源访问的压力. 所以经常要用到且不会频繁改变且被用户共享的 ...
 - ASP.NET Core 中的缓存
		
目录 缓存的基本概念 缓存原理 缓存设计 分布式缓存 Memcache 与 Redis 的比较 缓存穿透,缓存击穿,缓存雪崩解决方案 数据一致性 使用内置 MemoryCache 使用分布式缓存 Re ...
 - 第十二节:Asp.Net Core 之分布式缓存(SQLServer和Redis)
		
一. 整体说明 1. 说明 分布式缓存通常是指在多个应用程序服务器的架构下,作为他们共享的外部服务共享缓存,常用的有SQLServer.Redis.NCache. 特别说明一下:这里的分布式是 ...
 - 第十一节:Asp.Net Core 之内容缓存(IMemoryCache)
		
1. 整体说明 ASP.NET Core 支持多种不同的缓存,最简单的缓存基于 IMemoryCache,它表示存储在 Web 服务器内存中的缓存,内存缓存可以存储任何对象,存储形式键值对,需要 .n ...
 
随机推荐
- Python第一个请求接口
			
1.普通get请求 import requests import json login_res=requests.post(url='http://joy.web.com:8090/login',da ...
 - Excel查找匹配函数的16种方法
			
作者:高顿初级会计链接:https://zhuanlan.zhihu.com/p/79795779来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 1.普通查找 查找李晓 ...
 - Java单体应用 - Markdown - 03.高级技巧
			
原文地址:http://www.work100.net/training/monolithic-markdown-advance.html 更多教程:光束云 - 免费课程 高级技巧 序号 文内章节 视 ...
 - 《爬虫学习》(二)(urllib库使用)
			
urllib库是Python中一个最基本的网络请求库.可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据. 1.urlopen函数: 在Python3的urllib库中,所有 ...
 - List自定义排序 (例子省份排序)
			
//待排序集合 List<String> list=new ArrayList<String>(); list.add("辽宁"); list.add(&q ...
 - BZOJ 1152 歌唱王国
			
题目传送门 分析: 这道题很神仙,我们给出低配版解法和高配版解法2333 低配版: 首先知道这样一个公式...(证明去高配版) 当一个字符串S其中S [ 1 , i ] = S [ n - i + 1 ...
 - CTF--HTTP服务--SQL注入POST参数-注入HTTP报文
			
开门见山 1. 扫描靶机 2. 对靶机开放端口进行扫描 3. 扫描全部信息 4. 用nikto -host 探测敏感信息 5. 用dirb探测敏感目录 6. 打开一些目录探测出的网页进行查看 7. 再 ...
 - Jutil 单元测试
			
eclipse 自身集成了jtuil,右击项目,点击bulidpath,addjar,如下所示添加jutil 新建一个Junit的测试类用来测试上面的测试方法,新增Junit的测试类方法如下: // ...
 - Fedora 安装及配置
			
引言 最近学习课程要用到Linux,之前装的Ubuntu双系统被我删掉了(因为后来发现那个WSL,win子系统还挺好用的),所以上午用虚拟机再装了一下老师给的Ubuntu16,也不知道怎么回事特别卡, ...
 - LUA学习笔记(第5-6章)
			
x = a or b 如果a为真则x = a 如果a为假则x = b print(a .. b) 任何非nil类型都会被连接为字符串,输出 多重返回值 local s,e = string.find( ...