Talk about responsecaching in ASP. NET Core

Source: Internet
Author: User
Tags httpcontext browser cache

Objective

Most of the previous blogs are about caching data, so let's change the flavor today. To talk about responsecaching in ASP. NET core, which is often called HTTP caching, which is closely related to responsecaching.

Before reading this article, the default is that you have HTTP cache-related basics, primarily Cache-control-related.

Two related blogs are also posted here:

    • Viewing HTTP caching through the browser
    • HTTP protocol (quad) caching

Back to the point, for the responsecaching in ASP. NET core, this article mainly about three related small content

    1. Client (browser) caching
    2. Server-Side Caching
    3. Static file Caching
Client (browser) caching

The main thing here is to do this by setting the HTTP response header. There are two main ways of doing this:

First, directly with the response object to set.

There are two ways to do this, and the sample code is as follows:

publicIndex(){    //直接一,简单粗暴,不要拼写错了就好~~    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)    //};    returnView();}

The two effects are the same, roughly as follows:

They all add to the response header Cache-Control: public, max-age=600 , and some might ask, what's the use of this?

Then we'll look at the map again and it should be a lot clearer.

A breakpoint is set in the code beforehand, normally, as long as the request for this action comes in.

But it can be found that only the first time into the break point, the other directly open not in, but directly return the results to us, which also means that the cache has worked.

Again, take a look at the figure below, which from disk cache is enough to indicate that it does not request a result from the server, but rather directly from the local.

Note: If it is refreshed, it will still enter the breakpoint. Here you need to distinguish between good refresh, address bar return and other behaviors. There are some differences between browsers, which can be simulated with fiddler and Postman.

In the above practice, we mix the code of the header information with the business code, which is obviously not appropriate.

Here's a look at the second approach, and it's a more recommended approach.

Second, use Responsecacheattribute to deal with cache-related things.

For the same configuration as above, it is only necessary to set a property as follows.

[ResponseCache600)]publicIndex(){    returnView();}

The effect is consistent with the above! It's not a lot easier to deal with.

Since both of these methods can achieve the same effect, then responsecache this attribute essence is to write the corresponding value to the response header.

But we know that pure attribute can not complete this operation, which certainly has another mystery!

Turn over the source code, you can see that it implements the ifilterfactory this key interface.

[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,}); }}

In other words, the real function is responsecachefilter , the filter, the core code is as follows:

 Public void onactionexecuting(ActionExecutingContext context) {varheaders = 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; }}

Its nature is to write something to the head of the response.

The above example already knows the basic principle of responsecacheattribute operation, and then see how to configure other different effects.

The following table lists some of the commonly used settings and the generated response header information.

Settings for Responsecache Response Header
[Responsecache (Duration = +, location = responsecachelocation.client)] Cache-control:private, max-age=600
[Responsecache (location = Responsecachelocation.none, Nostore = True)] Cache-control:no-cache, No-store
[Responsecache (Duration = $, VaryByHeader = "user-agent")] Cache-control:public, max-age=60
Vary:user-agent

Note: If nostore is not set to True, then Duration must be assigned!

About Responsecacheattribute, there is a property that has to be mentioned:cacheprofilename!

It is equivalent to specifying a "configuration file" and setting some values for Responsecache in this profile.

At this point, you just need to specify the name of the "config file" on the Responsecacheattribute, instead of assigning a value to a property such as duration.

You need to get these "configuration files" ready when you add the MVC middleware!

The following example code adds two copies of "configuration Files", one of which is named Default, which is cached for 10 minutes, a copy named hourly, the default is cache for one hours, and some other optional configurations are also listed in comments.

Services.Addmvc(Options =>{options.)Cacheprofiles.ADD("Default",NewMicrosoft.Aspnetcore.MVC.CacheProfile{Duration = -,//Ten min}); Options.Cacheprofiles.ADD("Hourly",NewMicrosoft.Aspnetcore.MVC.CacheProfile{Duration = -* -,//1 hour        //location = Microsoft.AspNetCore.Mvc.ResponseCacheLocation.Any,        //nostore = True,        //varybyheader = "User-agent",        //varybyquerykeys = new string[] {"AAA"}});});

Now that "config file" is available, here's how to use the configuration! Just specify the name of Cacheprofilename on the attribute.

The sample code is as follows:

[ResponseCache"default")]publicIndex(){    returnView();}

There is also a Varybyquerykeys attribute in Responsecacheattribute, which can be cached according to different query parameters!

However, this attribute is used in conjunction with the contents of the next section, so this is not expanded.

Note: Responsecacheattribute can be added to the class above, can also be added to the method above, if the class and method are added, will take precedence over the method above the configuration.

Server-Side Caching

The first simple explanation of what the server cache here, compared to the previous client cache, it is to store things in the client, to use the time directly from the client to fetch!

In the same way, server-side caching is to store things on the server side, to use the time from the server to fetch.

It is important to note that if the server side of the cache hit, then it is directly return the results, but also do not access the contents of the action! A little bit like a proxy feeling.

This has an advantage over client-side caching, where the "refresh" page returns results from the cache for a certain amount of time, rather than having to visit the action again to get the results.

To enable server-side caching, you need to register the service in the pipeline, and the core code is the following two sentences.

publicvoidConfigureServices(IServiceCollection services){    services.AddResponseCaching();}publicvoidConfigure(IApplicationBuilder app, IHostingEnvironment env){    app.UseResponseCaching();}

Of course, only these two lines of code do not complete the server-side cache mentioned here. You also need the settings of the previous client cache to work together .

Can look at the following effect,

Simply explain this picture,

    1. The first time it is refreshed, it enters the middleware, then enters the action, returns the result, and fiddler records the request.
    2. The second time the New tab is opened, the results returned directly from the browser cache, i.e. no middleware, no entry into Action,fiddler, and no record of related requests
    3. The third time a browser, will enter the middleware, directly from the cache returned results, and did not enter the action, at this time fiddler also recorded the request, the response header contains the age

The third request responds with some information about the header as follows:

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

This age is changing! It is equivalent to the lifetime of the cache.

If you enable logging, you will also see some important journal information.

In the previous section, we also mention the Varybyquerykeys attribute in Responsecacheattribute, which needs to be used in conjunction with the Responsecaching middleware, which is also visible in the comments!

//// Summary://     Gets or sets the query keys to vary by.//// Remarks://     Microsoft.AspNetCore.Mvc.ResponseCacheAttribute.VaryByQueryKeys requires the//     response cache middleware.publicstringgetset; }

For example (not necessarily appropriate) to look at, assuming that there is now a movie list page (http://localhost:5001), you can use the URL address above the query parameters to determine the number of pages to display data.

If the code is written like this,

[ResponseCache600)]publicList(int0){    returnContent(page.ToString());}

The result will be as follows, three requests, the result of the page number 0 is returned! Page parameter, it doesn't work at all!

GET http://localhost:5001/Home/List HTTP/1.1Host: localhost:5001HTTP/1.1 200 OKDate: Thu, 05 Apr 2018 07:38:51 GMTContent-Type: text/plain; charset=utf-8Server: KestrelContent-Length: 1Cache-Control: public,max-age=6000GET http://localhost:5001/Home/List?page=2 HTTP/1.1Host: localhost:5001HTTP/1.1 200 OKDate: Thu, 05 Apr 2018 07:38:51 GMTContent-Type: text/plain; charset=utf-8Server: KestrelContent-Length: 1Cache-Control: public,max-age=600Age: 50GET http://localhost:5001/Home/List?page=5 HTTP/1.1Host: localhost:5001HTTP/1.1 200 OKDate: Thu, 05 Apr 2018 07:38:51 GMTContent-Type: text/plain; charset=utf-8Server: KestrelContent-Length: 1Cache-Control: public,max-age=600Age: 80

The correct approach should be to specify Varybyquerykeys, as follows:

[ResponseCache600newstring"page" })]publicList(int0){    returnContent(page.ToString());}

This time the result is the same as expected, the different parameters have corresponding results and the data are cached.

GET http://localhost:5001/Home/List HTTP/1.1Host: localhost:5001HTTP/1.1 200 OKDate: Thu, 05 Apr 2018 07:45:13 GMTContent-Type: text/plain; charset=utf-8Server: KestrelContent-Length: 1Cache-Control: public,max-age=6000GET http://localhost:5001/Home/List?page=2 HTTP/1.1Host: localhost:5001HTTP/1.1 200 OKDate: Thu, 05 Apr 2018 07:45:22 GMTContent-Type: text/plain; charset=utf-8Server: KestrelContent-Length: 1Cache-Control: public,max-age=6002GET http://localhost:5001/Home/List?page=5 HTTP/1.1Host: localhost:5001HTTP/1.1 200 OKDate: Thu, 05 Apr 2018 07:45:27 GMTContent-Type: text/plain; charset=utf-8Server: KestrelContent-Length: 1Cache-Control: public,max-age=6005

Responsecachingmiddleware here is using MemoryCache to read and write cache data. If the app restarts, the cached data will expire and be restarted.

Static file Caching

For some static files, such as permanent or less variable js,css, you can also cache them, avoid having them always initiate requests to the server, and these static files can be cached for a longer time!

If you have already used a CDN, this section of the content can be ignored for the moment ...

For static files,. NET Core has a separate staticfiles middleware, and if you want to do some processing on it, you also need to register in the pipeline.

UseStaticFilesThere are several overloaded methods, which are used in the method with the staticfileoptions parameter.

Because there's a onprepareresponse in Staticfileoptions that lets us modify the response header to achieve the HTTP caching effect.

//// 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.publicgetset; }

Here's a simple example:

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

The effect is as follows:

Some places to be aware of

First, the responsecaching middleware does not cache operations for the following scenarios!

    1. The status code for a request is not a
    2. A request method is not a GET or HEAD
    3. The header of a request contains Authorization
    4. The header of a request contains Set-cookie
    5. The header of a request contains only vary with a value of *
    6. ...

Second, when we use the antiforgery also need special attention!! It resets the Cache-control and Pragma of the response head directly to No-cache. In other words, the two are incompatible!

Details Visible defaultantiforgery.cs#l381

/// <summary>/// Sets the 'Cache-Control' header to 'no-cache, no-store' and 'Pragma' header to 'no-cache' overriding any user set value./// </summary>/// <param name="httpContext">The <see cref="HttpContext"/>.</param>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);    httpContext.Response.Headers[HeaderNames.CacheControl] = "no-cache, no-store";    httpContext.Response.Headers[HeaderNames.Pragma] = "no-cache";}

Of course, you should avoid using HTTP caching on this page when you use Antiforgery on a page!

It generates a hidden field in the form form, and the value of the hidden field is a generated token, do you want to cache it together?

Summarize

Using responsecaching in. NET core is still relatively straightforward, although there are some noteworthy areas that do not affect our normal use.

Of course, the most important thing is to use it properly! Use only where it is needed!

Finally enclose the address of the demo in the text

Responsecachingdemo

Talk about responsecaching in ASP. NET Core

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.