本文转自:https://www.ryadel.com/en/asp-net-core-static-files-cache-control-using-http-headers/

Every seasoned web developer experienced at least once some cache-related issue with static files. One of the most common scenarios is the following: you publish a new version of your web application that seems to work well, then – despite all your debug and tests – your friends, colleagues and/or users are unable to see the new stuff due to the fact that some old CSS or JS file is being still used by their client, despite you are 100% sure you replaced it on the server with a new version.

How can it even be possible? You ask to yourself for a split second, then you quickly realize that you’re hitting one of the simplest, yet most annoying issues of all time: the mere existence of a browser’s and/or proxy’s cache which is still holding the previous version of your updated file.

Until the last few years, this issue was mostly related to CSS and JS files only: however, with the increasing popularity of Single Page Applications and SPA-oriented frameworks such as ReactJS, AngularJS and Angular2, is now also affecting the index.html  page of these kind of apps.

Using ASP.NET 4 (and below)

If you’re using ASP.NET 4 or earlier, the issue can be easily overcome by adding some lines to the application’s web.config file, such as the following:

 
1
2
3
4
5
6
7
8
9
10
11
    <caching enabled="false" />
    <staticContent>
      <clientCache cacheControlMode="DisableCache" />
    </staticContent>
    <httpProtocol>
      <customHeaders>
        <add name="Cache-Control" value="no-cache, no-store" />
        <add name="Pragma" value="no-cache" />
        <add name="Expires" value="-1" />
      </customHeaders>
    </httpProtocol>

Placing this inside the <system.webServer>  node is all what you need to get disable all kind of client-sidecaching. However, if you’re using ASP.NET Core, you won’t be able to pull this out.

Using ASP.NET Core

As you might already know, the new ASP.NET Core’s configuration system has been re-architected from scratch: it doesn’t depend anymore to XML configuration files such as the web.config, so there’s no chance we can use it to control our static files cache.

The new pattern is based upon key/value settings that can be retrieved from a variety of sources, including Json files (such as the appsettings.json  file): once retrieved, they can be accessed within our code programmatically, using a technique not too different from what we could do with the old System.Configuration namespace.

Initial check

That said, the first thing to do is to make sure that our ASP.NET Core application is loading the appsettings.json file. Open the Startup.cs file and check if class costructor contains the following lines of code or not:

 
1
2
3
4
5
6
7
8
9
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }

If we started our project using the yeoman generator or any of the ASP.NET Core templates provided by Visual Studio 2015, everything should be already there: otherwise, just add it.

Setting the HTTP Headers for Static Files

Right after that, keep the Startup.cs file open and scroll down until you reach the Configure method and add (or modify) the app.UseStaticFiles()  middleware to set a custom caching behaviour just like the following (relevant lines are highlighted):

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();
 
        // Configure a rewrite rule to auto-lookup for standard default files such as index.html.
        app.UseDefaultFiles();
        // Serve static files (html, css, js, images & more). See also the following URL:
        // https://docs.asp.net/en/latest/fundamentals/static-files.html for further reference.
        app.UseStaticFiles(new StaticFileOptions()
        {
            OnPrepareResponse = (context) =>
            {
                // Disable caching for all static files.
                context.Context.Response.Headers["Cache-Control"] = "no-cache, no-store";
                context.Context.Response.Headers["Pragma"] = "no-cache";
                context.Context.Response.Headers["Expires"] = "-1";
            }
        });
    }

Adding the appsettings.json file to the loop

Now that we learned how to change the default caching behaviour, we need to change these static values with some convenient references pointing to the appsettings.json file. That way we won’t have these settings hard-coded into our application sources and we’ll be able to change them using different settings files, such as an  appsettings.production.json  for production environments.

In order to do that, open the appsettings.json file (create it if it doesn’t already exists) and add the following key/value section (relevant lines highlighted):

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "StaticFiles": {
    "Headers": {
      "Cache-Control": "no-cache, no-store",
      "Pragma": "no-cache",
      "Expires": "-1"
    }
  }
}

Replacing values with references

Now we just need to replace the literal string values in the Startup.cs file with a reference to these configuration keys. We can do that in the following way (modified lines are highlighted):

 
1
2
3
4
5
6
7
8
9
10
app.UseStaticFiles(new StaticFileOptions()
{
    OnPrepareResponse = (context) =>
    {
        // Disable caching for all static files.
        context.Context.Response.Headers["Cache-Control"] = Configuration["StaticFiles:Headers:Cache-Control"];
        context.Context.Response.Headers["Pragma"] = Configuration["StaticFiles:Headers:Pragma"];
        context.Context.Response.Headers["Expires"] = Configuration["StaticFiles:Headers:Expires"];
    }
});

Learning how to use this new configuration pattern can be very useful, as it’s a great way to customize our web application’s settings.

For further informations regarding this topic, we strongly suggest reading the following great posts from the official ASP.NET Core documentation web site:

That’s it for now: happy cache control!

[转]ASP.NET Core: Static Files cache control using HTTP Headers的更多相关文章

  1. ASP.NET Core中使用Cache缓存

    ASP.NET Core中使用Cache缓存 缓存介绍: 通过减少生成内容所需的工作,缓存可以显著提高应用的性能和可伸缩性. 缓存对不经常更改的数据效果最佳. 缓存生成的数据副本的返回速度可以比从原始 ...

  2. [ASP.NET Core] Static File Middleware

    前言 本篇文章介绍ASP.NET Core里,用来处理静态档案的Middleware,为自己留个纪录也希望能帮助到有需要的开发人员. ASP.NET Core官网 结构 一个Web站台最基本的功能,就 ...

  3. asp.net core 使用html文件

    在asp.net core 项目中,使用html文件一般通过使用中间件来提供服务: 打开 NuGet程序管理控制台 输入install-package Microsoft.aspnetcore.sta ...

  4. asp.net core 系列之Reponse caching之cache in-memory (2)

    这篇文章(主要翻译于官网,水平有限,见谅)讲解asp.net core 中的 Cache in-memory (内存缓存). Cache in-memory in ASP.NET Core Cachi ...

  5. Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core

    本文内容为转载,重新排版以供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core --- ...

  6. C# 6 与 .NET Core 1.0 高级编程 - 40 ASP.NET Core(上)

    译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 40 章  ASP.NET Core(上)),不对的地方欢迎指出与交流. 章节出自<Professiona ...

  7. ASP.NET Core 使用 Redis 客户端

    Mac OS 安装 Redis(用于连 Redis 服务器,方便查看数据):https://redis.io/topics/quickstart wget http://download.redis. ...

  8. ASP.NET Core MVC如何上传文件及处理大文件上传

    用文件模型绑定接口:IFormFile (小文件上传) 当你使用IFormFile接口来上传文件的时候,一定要注意,IFormFile会将一个Http请求中的所有文件都读取到服务器内存后,才会触发AS ...

  9. asp.net core 系列之Response caching(1)

    这篇文章简单的讲解了response caching: 讲解了cache-control,及对其中的头和值的作用,及设置来控制response caching; 简单的罗列了其他的缓存技术:In-me ...

随机推荐

  1. Breathe me

    Help, I have done it again 帮帮我,我又做错了. I have been here many times before 哪怕这已经不是一两次了. Hurt myself ag ...

  2. shell中的常用条件判断

    -e :该“文件名”是否存在.exit-d :该文件名是否为目录.dir-f  :该文件名是否为普通文件.file -b:该文件是否为块文件.block -r :该文件是否具有可读属性 read-w ...

  3. entity.Database.SqlQuery() 和entity.Database.SqlCommand()

    原文地址: http://msdn.microsoft.com/en-us/library/gg715124(v=vs.103) 使用 EF 4.1 或者更新版本, 你可以直接执行任何数据库命令. 在 ...

  4. 【webpack】流行的前端模块化工具webpack初探

    从开发文件到生产文件   有一天我突然意识到一个问题,在使用react框架搭建应用时,我使用到了sass/less,JSX模版以及ES6的语法在编辑器下进行开发,使用这些写法是可以提高开发的效率.可是 ...

  5. 第77节:Java中的事务和数据库连接池和DBUtiles

    第77节:Java中的事务和数据库连接池和DBUtiles 前言 看哭你,字数:8803,承蒙关照,谢谢朋友点赞! 事务 Transaction事务,什么是事务,事务是包含一组操作,这组操作里面包含许 ...

  6. Kali学习笔记36:AVWS10的使用

    AVWS是一款商业Web扫描工具 适用于Windows操作系统 功能强大,必须掌握 AVWS11以上是Web形式,AVWS10是桌面应用形式 下载安装破解这些基本操作就不说了,百度即可 从安装好开始: ...

  7. Dockerfile常用指令

    FROM 构建的新镜像基于那个镜像 , FROM ubuntu:14 MAINTAINER 镜像维护者姓名或邮箱地址 RUN CMD EXPOSE  声明容器运行服务的端口 ENV ADD  拷贝文件 ...

  8. Python档案袋(脚本执行和输入输出)

    脚本的执行: 1.执行时确定解释器为Python3 python3 脚本名 2.在代码开始行确定解释器为Python3,与shell相似 env命令表示全局搜索Python3解释器 #!/usr/bi ...

  9. 关于 Kubernetes 中的 Volume 与 GlusterFS 分布式存储

    容器中持久化的文件生命周期是短暂的,如果容器中程序崩溃宕机,kubelet 就会重新启动,容器中的文件将会丢失,所以对于有状态的应用容器中持久化存储是至关重要的一个环节:另外很多时候一个 Pod 中可 ...

  10. Linux编程 10 (shell外部命令与内建命令,alias ,type命令)

    一.  内部命令 Linux命令有内部命令(内建命令)和外部命令之分,内部命令和外部命令功能基本相同,但也有些细微差别.内部命令不需要使用子进程来执行,它们已经和shell编译成一体,作为shell工 ...