I have a question related to cache invalidation techniques... I am trying to implement a mechanism for my website, that automatically inv开发者_如何学Pythonalidates browser cache (css, images...). I want to be able to programatically invalidate browser cache, whenever I update the website (change images or styles);
For example: for the current release, among others, the css and some of the images have changed. In this situation I want that after the update is finished, when a user performs a request to the website, his browser's cache to get automatically invalidated, thus forcing the re-download of the new images and styles. This should be done only for the client's first request... the following ones should be retrieved from cache (so setting the no-cache pragma is out of the question).
Here's what i've tried: in the BeginRequest event handler, I added the following lines:
Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate);
Response.Cache.SetETag("\"e111293b17594f1487d136ea7e9314ac\"");
this sets the ETag in the response headers. I figured that if I change this ETag at each release, and set it at each request, the cache will be invalidated, but it seems that it is not. I used Live HTTP headers to see the results and the ETAG is correctly set up for the response, but the css and images are still taken from cache.
Any ideas of how I could accomplish this, or if it can be accomplished at all?
I have run into issues like this in the past. Unfortunately I couldn't find a really nice way to accomplish this so I had to come up with a workaround. I was only dealing with this issue for CSS files so I added an extra querystring parameter to every CSS reference, for example
<link rel="stylesheet" type="text/css"
href="default.css?buildnumber=<%= Buildnumber %>" />
The build number gets incremented with each release so the browser was forced to go look for this new file. Not an ideal solution, but it worked without a hitch.
For those who are seeking for a MVC5 solution:
Step1: Change the AssemblyInfo.cs file of the project to the following
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.*")]
Step 2: Create a class to get the current version info on your project:
public class Versioner
{
public static Version GetVersion()
{
Assembly thisAssem = typeof(Versionador).Assembly;
AssemblyName thisAssemName = thisAssem.GetName();
Version vrs = thisAssemName.Version;
return vrs;
}
//Not really necessary, just if you need to show this info
public static string GetDataBuild()
{
Version version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
DateTime buildDate = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2);
string displayableVersion = $"{version} ({buildDate})";
return displayableVersion;
}
}
Step 3: Call the class methods in the views which needs cache auto-refresh on new builds.
@{
Version _ver = <MyProject>.Classes.Extensions.Versioner.GetVersion();
}
//here, <MyProject>.Classes.Extensions is my path to the Versioner.cls class file, adjust it to your project's classes path
Step 4: Use the variable with the version string to append to your scripts or .css files
<script src="~/js/index.js?v=@_ver"></script>
<link href="/css/style.css?v=@_ver" rel="stylesheet" />
精彩评论