由於IIS提供文件服務和手錶改變當前的設置,IIS將始終發送重新驗證緩存頭,迫使瀏覽器來檢查更改。爲了擺脫這個問題,我們設計瞭如下所示的CachedRoute
,但是,這在ASP.NET MVC中運行良好,但幾乎沒有什麼變化,您也可以在ASP.NET WebForms中實現相同的功能。
此代碼還爲您提供將靜態資源移動到CDN的好處。
緩存版本網址前綴
我們必須拿出像/cached/version/
靜態內容版本,這不過只是一個URL前綴靜態資產。 version
可以是任何隨機字母數字字符串,完全沒用,但標識不同的版本。
那麼最簡單的方法之一是在URL中使用版本密鑰。
首先,在AssemblyInfo.cs中構建版本
[assembly: AssemblyVersion("1.5.*.*")]
離開,*作爲版本號替代,.NET編譯器會自動與每個版本遞增。
還是在應用程序設置定義版本遵循
<appSettings>
<add key="Static-Content-Version" value="1.5.445.55565"/>
<add key="CDNHost" value="cdn1111.cloudfront.net"/>
</appSettings>
// Route configuration
// set CDN if you have
string cdnHost = WebConfigrationManager.AppSettings["CDNHost"];
if(!string.IsEmpty(cdnHost)){
CachedRoute.CDNHost = cdnHost;
}
// get assembly build information
string version = typeof(RouteConfig).Assembly.GetName().Version.ToString();
CachedRoute.CORSOrigins = "*";
CachedRoute.Register(routes, TimeSpam.FromDays(30), version);
現在每一頁上,引用您的靜態內容,
<script src="@CachedRoute.CachedUrl("/scripts/jquery-1.11.1.js")"></script>
雖然呈現,頁面將呈現爲(不包括CDN)
<script src="/cached/1.5.445.55565/scripts/jquery-1.11.1.js"></script>
隨着CDN來
<script
src="//cdn111.cloudfront.net/cached/1.5.445.55565/scripts/jquery-1.11.1.js">
</script>
將版本放入URL路徑而不是查詢字符串會使CDN執行更好,因爲查詢字符串可以在CDN配置中忽略(通常是默認情況)。
優點 如果您將版本設置爲與組裝版本相同,則可以輕鬆地進行新建。否則,每次更改版本時都必須手動更改web.config。
CachedRoute類源於 https://github.com/neurospeech/atoms-mvc.net/blob/master/src/Mvc/CachedRoute.cs
public class CachedRoute : HttpTaskAsyncHandler, IRouteHandler
{
private CachedRoute()
{
// only one per app..
}
private string Prefix { get; set; }
public static string Version { get; private set; }
private TimeSpan MaxAge { get; set; }
public static string CORSOrigins { get; set; }
//private static CachedRoute Instance;
public static void Register(
RouteCollection routes,
TimeSpan? maxAge = null,
string version = null)
{
CachedRoute sc = new CachedRoute();
sc.MaxAge = maxAge == null ? TimeSpan.FromDays(30) : maxAge.Value;
if (string.IsNullOrWhiteSpace(version))
{
version = WebConfigurationManager.AppSettings["Static-Content-Version"];
if (string.IsNullOrWhiteSpace(version))
{
version = Assembly.GetCallingAssembly().GetName().Version.ToString();
}
}
Version = version;
var route = new Route("cached/{version}/{*name}", sc);
route.Defaults = new RouteValueDictionary();
route.Defaults["version"] = "1";
routes.Add(route);
}
public override bool IsReusable
{
get
{
return true;
}
}
public static string CDNHost { get; set; }
public static HtmlString CachedUrl(string p)
{
if (!p.StartsWith("/"))
throw new InvalidOperationException("Please provide full path starting with /");
string cdnPrefix = string.IsNullOrWhiteSpace(CDNHost) ? "" : ("//" + CDNHost);
return new HtmlString(cdnPrefix + "/cached/" + Version + p);
}
public override async Task ProcessRequestAsync(HttpContext context)
{
var Response = context.Response;
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetMaxAge(MaxAge);
Response.Cache.SetExpires(DateTime.Now.Add(MaxAge));
if (CORSOrigins != null)
{
Response.Headers.Add("Access-Control-Allow-Origin", CORSOrigins);
}
string FilePath = context.Items["FilePath"] as string;
var file = new FileInfo(context.Server.MapPath("/" + FilePath));
if (!file.Exists)
{
throw new FileNotFoundException(file.FullName);
}
Response.ContentType = MimeMapping.GetMimeMapping(file.FullName);
using (var fs = file.OpenRead())
{
await fs.CopyToAsync(Response.OutputStream);
}
}
IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)
{
//FilePath = requestContext.RouteData.GetRequiredString("name");
requestContext.HttpContext.Items["FilePath"] = requestContext.RouteData.GetRequiredString("name");
return (IHttpHandler)this;
}
}
爲第一請求樣品響應頭
Access-Control-Allow-Origin:*
Cache-Control:public
Content-Length:453
Content-Type:image/png
Date:Sat, 04 Jul 2015 08:04:55 GMT
Expires:Mon, 03 Aug 2015 00:46:43 GMT
Server:Microsoft-IIS/8.5
Via:1.1 ********************************
X-Amz-Cf-Id: ******************************
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:5.2
X-Cache:Miss from cloudfront
X-Powered-By:ASP.NET
見,沒有ETag的,依數據,上次修改或驗證報頭和也看到明確的Expires標題,當您發送明確的Expires標題時,瀏覽器將永遠不會嘗試驗證緩存。
你不能*力量*瀏覽器做任何事。 – Richard