谈谈ASP.NET Core中的ResponseCaching

谈谈ASP.NET Core中的ResponseCaching,第1张

概述前言前面的博客谈的大多数都是针对数据的缓存,今天我们来换换口味。来谈谈在ASP.NET Core中的ResponseCaching,与ResponseCaching关联密切的也就是常说的HTTP缓存。在阅读本文内容之前,默认各位有HTTP缓存相关的基础,主要是Cache-Control相关的。这里也贴两篇相关的博客:透过浏览器看HTTP缓存HTTP协议 (四) 缓存回到正题,对于ASP.NET Core中的ResponseCaching,本文主要讲三个相关的小内容客户端(浏览器)缓存服务端缓存静态文件缓存客户端(浏览器)缓存这里主要是通过设置HTTP的响应头来完成这件事的。方法主要有两种:其一,直接用Response对象去设置。这种方式也有两种写法,示例代码如下:public IActionResult Index(){//直接一,简单粗暴,不要拼写错了就好~~Response.Headers[Microsoft.Net.Http.Headers.HeaderNames.CacheControl] = "public, max-age=600";//直接二,略微优雅点//Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue()//{// Public = true,// MaxAge = TimeSpan.FromSeconds(600)//};return View();}这两者效果是一样的,大致如下:它们都会给响应头加上 Cache-Control: public, max-age=600,可能有人会问,加上这个有什么用?那我们再来看张动图,应该会清晰不少。这里事先在代码里面设置了一个断点,正常情况下,只要请求这个action都是会进来的。但是从上图可以发现,只是第一次才进了断点,其他直接打开的都没有进,而是直接返回结果给我们了,这也就说明缓存起作用了。同样的,再来看看下面的图,from disk cache也足以说明,它并没有请求到服务器,而是直接从本地返回的结果。注:如果是刷新的话,还是会进断点的。这里需要区分好刷新,地址栏回车等行为。不同浏览器也有些许差异,这里可以用fiddler和postman来模拟。在上面的做法中,我们将设置头部信息的代码和业务代码混在一起了,这显然不那么合适。下面来看看第二种方法,也是比较推荐的方法。其二,用ResponseCacheAttribute去处理缓存相关的事情。对于和上面的同等配置,只需要下面这样简单设置一个属性就可以了。[ResponseCache(Duration = 600)]public IActionResult Index(){return View();}效果和上面是一致的!处理起来是不是简单多了。既然这两种方式都能完成一样的效果,那么ResponseCache这个Attribute本质也是往响应头写了相应的值。但是我们知道,纯粹的Attribute并不能完成这一 *** 作,其中肯定另有玄机!翻了一下源码,可以看到它实现了IFilterFactory这个关键的接口。[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]public class ResponseCacheAttribute : Attribute, IFilterFactory, IOrderedFilter{public IFilterMetadata CreateInstance(IServiceProvider serviceProvider){//..return new ResponseCacheFilter(new CacheProfile{Duration = _duration,Location = _location,NoStore = _noStore,VaryByHeader = VaryByHeader,VaryByQueryKeys = VaryByQueryKeys,});}}也就是说,真正起作用的是ResponseCacheFilter这个Filter,核心代码如下:public void OnActionExecuting(ActionExecutingContext context){var headers = context.HttpContext.Response.Headers;// Clear all headersheaders.Remove(HeaderNames.Vary);headers.Remove(HeaderNames.CacheControl);headers.Remove(HeaderNames.Pragma);if (!string.IsNullOrEmpty(VaryByHeader)){headers[HeaderNames.Vary] = VaryByHeader;}if (NoStore){headers[HeaderNames.CacheControl] = "no-store";// Cache-control: no-store, no-cache is valid.if (Location == ResponseCacheLocation.None){headers.AppendCommaSeparatedValues(HeaderNames.CacheControl, "no-cache");headers[HeaderNames.Pragma] = "no-cache";}}else{headers[HeaderNames.CacheControl] = cacheControlValue;}}它的本质自然就是给响应头部写了一些东西。通过上面的例子已经知道了ResponseCacheAttribute运作的基本原理,下面再来看看如何配置出其他不同的效果。下面的表格列出了部分常用的设置和生成的响应头信息。ResponseCache的设置响应头[ResponseCache(Duration = 600, Location = ResponseCacheLocation.Client)]Cache-Control: private, max-age=600[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]Cache-Control:no-cache, no-store[ResponseCache(Duration = 60, VaryByHeader = "User-Agent")]Cache-Control : public, max-age=60Vary : User-Agent注:如果NoStore没有设置成true,则Duration必须要赋值!关于ResponseCacheAttribute,还有一个不得不提的属性:CacheProfileName!它相当于指定了一个“配置文件”,并在这个“配置文件”中设置了ResponseCache的一些值。这个时候,只需要在ResponseCacheAttribute上面指定这个“配置文件”的名字就可以了,而不用在给Duration等属性赋值了。在添加MVC这个中间件的时候就需要把这些“配置文件”准备好!下面的示例代码添加了两份“配置文件”,其中一份名为default,默认是缓存10分钟,还有一份名为Hourly,默认是缓存一个小时,还有一些其他可选配置也用注释的方式列了出来。services.AddMvc(options =>{options.CacheProfiles.Add("default", new Microsoft.AspNetCore.Mvc.CacheProfile{Duration = 600, // 10 min});options.CacheProfiles.Add("Hourly", new Microsoft.AspNetCore.Mvc.CacheProfile{Duration = 60 * 60, // 1 hour//Location = Microsoft.AspNetCore.Mvc.ResponseCacheLocation.Any,//NoStore = true,//VaryByHeader = "User-Agent",//VaryByQueryKeys = new string[] { "aaa" }});});现在“配置文件”已经有了,下面就是使用这些配置了!只需要在Attribute上面指定CacheProfileName的名字就可以了。示例代码如下:[ResponseCache(CacheProfileName = "default")]public IActionResult Index(){return View();}ResponseCacheAttribute中还有一个VaryByQueryKeys的属性,这个属性可以根据不同的查询参数进行缓存!但是这个属性的使用需要结合下一小节的内容,所以这里就不展开了。注:ResponseCacheAttribute即可以加在类上面,也可以加在方法上面,如果类和方法都加了,会优先采用方法上面的配置。服务端缓存先简单解释一下这里的服务端缓存是什么,对比前面的客户端缓存,它是将东西存放在客户端,要用的时候就直接从客户端去取!同理,服务端缓存就是将东西存放在服务端,要用的时候就从服务端去取。需要注意的是,如果服务端的缓存命中了,那么它是直接返回结果的,也是不会去访问Action里面的内容!有点类似代理的感觉。这个相比客户端缓存有一个好处,在一定时间内,“刷新”页面的时候会从这里的缓存返回结果,而不用再次访问Action去拿结果。要想启用服务端缓存,需要在管道中去注册这个服务,核心代码就是下面的两句。public void ConfigureServices(IServiceCollection services){services.AddResponseCaching();}public void Configure(IApplicationBuilder app, IHostingEnvironment env){app.UseResponseCaching();}当然,仅有这两句代码,并不能完成这里提到的服务端缓存。还需要前面客户端缓存的设置,两者结合起来才能起作用。可以看看下面的效果,简单解释一下这张图,第一次刷新的时候,会进入中间件,然后进入Action,返回结果,Fiddler记录到了这一次的请求第二次打开新标签页,直接从浏览器缓存中返回的结果,即没有进入中间件,也没有进入Action,Fiddler也没有记录到相关请求第三次换了一个浏览器,会进入中间件,直接由缓存返回结果,并没有进入Action,此时Fiddler也将该请求记录了下来,响应头包含了Age第三次请求响应头部的部分信息如下:Age: 16Cache-Control: public,max-age=600这个Age是在变化的!它就等价于缓存的寿命。如果启用了日志,也会看到一些比较重要的日记信息。在上一小节中,我们还有提到ResponseCacheAttribute中的VaryByQueryKeys这个属性,它需要结合ResponseCaching中间件一起用的,这点在注释中也是可以看到的!//// Summary:// Gets or sets the query keys to vary by.//// Remarks:// Microsoft.AspNetCore.Mvc.ResponseCacheAttribute.VaryByQueryKeys requ

<h2 ID="前言">前言

前面的博客谈的大多数都是针对数据的缓存,今天我们来换换口味。来谈谈在ASP.NET Core中的ResponseCaching,与ResponseCaching关联密切的也就是常说的http缓存。

在阅读本文内容之前,默认各位有http缓存相关的基础,主要是Cache-Control相关的。

这里也贴两篇相关的博客:

回到正题,对于ASP.NET Core中的ResponseCaching,本文主要讲三个相关的小内容

客户端(浏览器)缓存服务端缓存静态文件缓存

这里主要是通过设置http的响应头来完成这件事的。方法主要有两种:

其一,直接用Response对象去设置。

这种方式也有两种写法,示例代码如下:

public IActionResult Index(){    //直接一,简单粗暴,不要拼写错了就好~~    Response.headers[Microsoft.Net.http.headers.headernames.CacheControl] = "public,max-age=600";
//直接二,略微优雅点//Response.GetTyped<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s().CacheContr<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a> = new Microsoft.Net.<a href="https://m.jb51.cc/tag/http/" target="_blank" >http</a>.<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s.CacheContr<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a><a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>Value()//{//    Pub<a href="https://m.jb51.cc/tag/li/" target="_blank" >li</a>c = true,//    MaxAge = TimeSpan.FromSeconds(600)//};return V<a href="https://m.jb51.cc/tag/IE/" target="_blank" >IE</a>w();

}

这两者效果是一样的,大致如下:

它们都会给响应头加上 Cache-Control: public,max-age=600,可能有人会问,加上这个有什么用?

那我们再来看张动图,应该会清晰不少。

这里事先在代码里面设置了一个断点,正常情况下,只要请求这个action都是会进来的。

但是从上图可以发现,只是第一次才进了断点,其他直接打开的都没有进,而是直接返回结果给我们了,这也就说明缓存起作用了。

同样的,再来看看下面的图,from disk cache也足以说明,它并没有请求到服务器,而是直接从本地返回的结果。

注:如果是刷新的话,还是会进断点的。这里需要区分好刷新,地址栏回车等行为。不同浏览器也有些许差异,这里可以用fiddler和postman来模拟。

在上面的做法中,我们将设置头部信息的代码和业务代码混在一起了,这显然不那么合适。

下面来看看第二种方法,也是比较推荐的方法。

其二,用responsecacheAttribute去处理缓存相关的事情。

对于和上面的同等配置,只需要下面这样简单设置一个属性就可以了。

[responsecache(Duration = 600)]public IActionResult Index(){    return VIEw();}

效果和上面是一致的!处理起来是不是简单多了。

既然这两种方式都能完成一样的效果,那么responsecache这个Attribute本质也是往响应头写了相应的值。

但是我们知道,纯粹的Attribute并不能完成这一 *** 作,其中肯定另有玄机!

翻了一下源码,可以看到它实现了IFilterFactory这个关键的接口。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,AllowMultiple = false,inherited = true)]public class responsecacheAttribute : Attribute,IFilterFactory,IOrderedFilter{    public IFilterMetadata CreateInstance(IServiceProvIDer serviceProvIDer)    {        //..
    return new <a href="https://www.jb51.cc/tag/responsecache/" target="_blank" >responsecache</a>Filter(new CachePro<a href="https://m.jb51.cc/tag/file/" target="_blank" >file</a>    {        Duration = _duration,Location = _location,NoStore = _noStore,<a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>By<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a> = <a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>By<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>,<a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>By<a href="https://m.jb51.cc/tag/query/" target="_blank" >query</a>Keys = <a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>By<a href="https://m.jb51.cc/tag/query/" target="_blank" >query</a>Keys,});}

}

也就是说,真正起作用的是responsecacheFilter这个Filter,核心代码如下:

public voID OnActionExecuting(ActionExecutingContext context){    var headers = context.httpContext.Response.headers;
// Clear all <a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s.Remove(<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.<a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>);<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s.Remove(<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.CacheContr<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>);<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s.Remove(<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.Pragma);if (!string.IsN<a href="https://m.jb51.cc/tag/ul/" target="_blank" >ul</a>lOrEmpty(<a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>By<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>)){    <a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s[<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.<a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>] = <a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>By<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>;}if (NoStore){    <a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s[<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.CacheContr<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>] = "no-store";    // Cache-contr<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>: no-store,no-cache is val<a href="https://m.jb51.cc/tag/ID/" target="_blank" >ID</a>.    if (Location == <a href="https://www.jb51.cc/tag/responsecache/" target="_blank" >responsecache</a>Location.None)    {        <a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s.AppendCommaSep<a href="https://www.jb51.cc/tag/ara/" target="_blank" >ara</a>tedValues(<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.CacheContr<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>,"no-cache");        <a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s[<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.Pragma] = "no-cache";    }}else{    <a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s[<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.CacheContr<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>] = cacheContr<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>Value;}

}

它的本质自然就是给响应头部写了一些东西。

通过上面的例子已经知道了responsecacheAttribute运作的基本原理,下面再来看看如何配置出其他不同的效果。

下面的表格列出了部分常用的设置和生成的响应头信息。

responsecache的设置响应头

注:如果NoStore没有设置成true,则Duration必须要赋值!

关于responsecacheAttribute,还有一个不得不提的属性:CacheProfilename!

它相当于指定了一个“配置文件”,并在这个“配置文件”中设置了responsecache的一些值。

这个时候,只需要在responsecacheAttribute上面指定这个“配置文件”的名字就可以了,而不用在给Duration等属性赋值了。

在添加MVC这个中间件的时候就需要把这些“配置文件”准备好!

下面的示例代码添加了两份“配置文件”,其中一份名为default,默认是缓存10分钟,还有一份名为Hourly,默认是缓存一个小时,还有一些其他可选配置也用注释的方式列了出来。

services.AddMvc(options =>{    options.CacheProfiles.Add("default",new Microsoft.AspNetCore.Mvc.CacheProfile    {        Duration = 600,// 10 min    });
options.CachePro<a href="https://m.jb51.cc/tag/file/" target="_blank" >file</a>s.Add("Hourly",new Microsoft.AspNetCore.Mvc.CachePro<a href="https://m.jb51.cc/tag/file/" target="_blank" >file</a>{    Duration = 60 * 60,// 1 hour    //Location = Microsoft.AspNetCore.Mvc.<a href="https://www.jb51.cc/tag/responsecache/" target="_blank" >responsecache</a>Location.Any,//NoStore = true,//<a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>By<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a> = "User-Agent",//<a href="https://www.jb51.cc/tag/vary/" target="_blank" >vary</a>By<a href="https://m.jb51.cc/tag/query/" target="_blank" >query</a>Keys = new string[] { "aaa" }});

});

现在“配置文件”已经有了,下面就是使用这些配置了!只需要在Attribute上面指定CacheProfilename的名字就可以了。

示例代码如下:

[responsecache(CacheProfilename = "default")]public IActionResult Index(){    return VIEw();}

responsecacheAttribute中还有一个varyByqueryKeys的属性,这个属性可以根据不同的查询参数进行缓存!

但是这个属性的使用需要结合下一小节的内容,所以这里就不展开了。

注:responsecacheAttribute即可以加在类上面,也可以加在方法上面,如果类和方法都加了,会优先采用方法上面的配置。

先简单解释一下这里的服务端缓存是什么,对比前面的客户端缓存,它是将东西存放在客户端,要用的时候就直接从客户端去取!

同理,服务端缓存就是将东西存放在服务端,要用的时候就从服务端去取。

需要注意的是,如果服务端的缓存命中了,那么它是直接返回结果的,也是不会去访问Action里面的内容!有点类似代理的感觉。

这个相比客户端缓存有一个好处,在一定时间内,“刷新”页面的时候会从这里的缓存返回结果,而不用再次访问Action去拿结果。

要想启用服务端缓存,需要在管道中去注册这个服务,核心代码就是下面的两句。

public voID ConfigureServices(IServiceCollection services){    services.AddResponseCaching();}

public voID Configure(IApplicationBuilder app,IHostingEnvironment env)
{
app.UseResponseCaching();
}

当然,仅有这两句代码,并不能完成这里提到的服务端缓存。还需要前面客户端缓存的设置,两者结合起来才能起作用。

可以看看下面的效果,

简单解释一下这张图,

第一次刷新的时候,会进入中间件,然后进入Action,返回结果,fiddler记录到了这一次的请求第二次打开新标签页,直接从浏览器缓存中返回的结果,即没有进入中间件,也没有进入Action,fiddler也没有记录到相关请求第三次换了一个浏览器,会进入中间件,直接由缓存返回结果,并没有进入Action,此时fiddler也将该请求记录了下来,响应头包含了Age

第三次请求响应头部的部分信息如下:

Age: 16Cache-Control: public,max-age=600

这个Age是在变化的!它就等价于缓存的寿命。

如果启用了日志,也会看到一些比较重要的日记信息。

在上一小节中,我们还有提到responsecacheAttribute中的varyByqueryKeys这个属性,它需要结合ResponseCaching中间件一起用的,这点在注释中也是可以看到的!

//// Summary://     Gets or sets the query keys to vary by.//// Remarks://     Microsoft.AspNetCore.Mvc.responsecacheAttribute.varyByqueryKeys requires the//     response cache mIDdleware.public string[] varyByqueryKeys { get; set; }

举个例子(不一定很合适)来看看,假设现在有一个电影列表页面(),可以通过在URL地址上面加查询参数来决定显示第几页的数据。

如果代码是这样写的,

[ResponseCache(Duration = 600)]public IActionResult List(int page = 0){    return Content(page.ToString());}

结果就会像下面这样,三次请求,返回的都是页码为0的结果!page参数,压根就没起作用!

GET http://localhost:5001/Home/List HTTP/1.1Host: localhost:5001

HTTP/1.1 200 OK
Date: Thu,05 Apr 2018 07:38:51 GMT
Content-Type: text/plain; charset=utf-8
Server: Kestrel
Content-Length: 1
Cache-Control: public,max-age=600

0

GET http://localhost:5001/Home/List?page=2 HTTP/1.1
Host: localhost:5001

HTTP/1.1 200 OK
Date: Thu,max-age=600
Age: 5

0

GET http://localhost:5001/Home/List?page=5 HTTP/1.1
Host: localhost:5001

HTTP/1.1 200 OK
Date: Thu,max-age=600
Age: 8

0

正确的做法应该是要指定VaryByQueryKeys,如下所示:

[ResponseCache(Duration = 600,VaryByQueryKeys = new string[] { "page" })]public IActionResult List(int page = 0){    return Content(page.ToString());}

这个时候的结果就是和预期的一样了,不同参数都有对应的结果并且这些数据都缓存了起来。

GET http://localhost:5001/Home/List HTTP/1.1Host: localhost:5001

HTTP/1.1 200 OK
Date: Thu,05 Apr 2018 07:45:13 GMT
Content-Type: text/plain; charset=utf-8
Server: Kestrel
Content-Length: 1
Cache-Control: public,05 Apr 2018 07:45:22 GMT
Content-Type: text/plain; charset=utf-8
Server: Kestrel
Content-Length: 1
Cache-Control: public,max-age=600

2

GET http://localhost:5001/Home/List?page=5 HTTP/1.1
Host: localhost:5001

HTTP/1.1 200 OK
Date: Thu,05 Apr 2018 07:45:27 GMT
Content-Type: text/plain; charset=utf-8
Server: Kestrel
Content-Length: 1
Cache-Control: public,max-age=600

5

ResponseCachingMiddleware在这里是用了MemoryCache来读写缓存数据的。如果应用重启了,缓存的数据就会失效,要重新来过。

对于一些常年不变或比较少变的js,css等静态文件,也可以把它们缓存起来,避免让它们总是发起请求到服务器,而且这些静态文件可以缓存更长的时间!

如果已经使用了CDN,这一小节的内容就可以暂且忽略掉了。。。

对于静态文件,.NET Core有一个单独的StaticFiles中间件,如果想要对它做一些处理,同样需要在管道中进行注册。

UseStaticFiles有几个重载方法,这里用的是带StaticFileOptions参数的那个方法。

因为StaticFileOptions里面有一个OnPrepareResponse可以让我们修改响应头,以达到HTTP缓存的效果。

//// Summary://     Called after the status code and headers have been set,but before the body has//     been written. This can be used to add or change the response headers.public Action OnPrepareResponse { get; set; }

下面来看个简单的例子:

app.UseStaticFiles(new StaticFileOptions{    OnPrepareResponse = context =>    {        context.Context.Response.GetTypedHeaders().CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue        {             Public = true,//for 1 year            MaxAge = System.TimeSpan.FromDays(365)        };    }});

此时的效果如下:

其一,ResponseCaching中间件对下面的情况是不会进行缓存 *** 作的!

一个请求的Status Code不是200一个请求的Method不是GET或HEAD一个请求的Header包含Authorization一个请求的Header包含Set-Cookie一个请求的Header包含仅有值为*的Vary...

其二,当我们使用了Antiforgery的时候也要特别的注意!!它会直接把响应头部的Cache-ControlPragma重置成no-cache。换句话说,这两者是水火不容的!

详情可见

/// /// Sets the 'Cache-Control' header to 'no-cache,no-store' and 'Pragma' header to 'no-cache' overrIDing any user set value./// /// protected virtual voID SetDoNotCacheheaders(httpContext httpContext){    // Since antifogery token generation is not very obvIoUs to the end users (ex: MVC's form tag generates them    // by default),log a warning to let users kNow of the change in behavior to any cache headers they might    // have set explicitly.    LogCacheheaderOverrIDeWarning(httpContext.Response);
<a href="https://m.jb51.cc/tag/http/" target="_blank" >http</a>Context.Response.<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s[<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.CacheContr<a href="https://m.jb51.cc/tag/ol/" target="_blank" >ol</a>] = "no-cache,no-store";<a href="https://m.jb51.cc/tag/http/" target="_blank" >http</a>Context.Response.<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a>s[<a href="https://m.jb51.cc/tag/header/" target="_blank" >header</a><a href="https://m.jb51.cc/tag/name/" target="_blank" >name</a>s.Pragma] = "no-cache";

}

当然,在某个页面用到了Antiforgery的时候,也该避免在这个页面使用http缓存!

它会在form表单中生成一个隐藏域,并且隐藏域的值是一个生成的token ,难道还想连这个一起缓存?

在.NET Core中用ResponseCaching还是比较简单的,虽然还有一些值得注意的地方,但是并不影响我们的正常使用。

当然,最重要的还是合理使用!仅在需要的地方使用!

最后附上文中Demo的地址

href="https://github.com/catcherwong/Demos/tree/master/src/ResponseCachingDemo">ResponseCachingDemo

总结

以上是内存溢出为你收集整理的谈谈ASP.NET Core中的ResponseCaching全部内容,希望文章能够帮你解决谈谈ASP.NET Core中的ResponseCaching所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1256014.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存