简体   繁体   English

如何向ASP.NET MVC站点中的所有图像添加缓存破坏者

[英]How to add a cache buster to all images in an ASP.NET MVC site

I am trying to improve the performance of a large ASP.NET MVC website and I am currently looking for a way of adding a cache busting query string to image requests in such a way that I don't have to go through all the views and CSS and change each image reference. 我正在尝试改善大型ASP.NET MVC网站的性能,并且目前正在寻找一种向图像请求中添加缓存清除查询字符串的方式,而不必遍历所有视图和CSS并更改每个图像引用。

Desired result 所需结果

To verify if the cache buster is being added I am using the Firebug extension in Firefox and what I am looking to see is something like this (screenshot taken from another website) 为了验证是否添加了缓存清除器,我正在Firefox中使用Firebug扩展,我希望看到的是这样的东西(截取自其他网站的截图)

在此处输入图片说明

What I've tried 我尝试过的

The simplest answer seemed to me to create a custom HttpModule that intercepted any image request and then appended the cache busting query string to the request URL. 对我来说,最简单的答案似乎是创建一个自定义HttpModule,它可以拦截任何图像请求,然后将缓存清除查询字符串附加到请求URL。 So I wrote the following class 所以我写了下面的课

public class CacheBusterImageHandler : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.BeginRequest += this.BeginRequest;
    }

    public void Dispose()
    {            
    }

    public void BeginRequest(object sender, EventArgs e)
    {
        // This conditional check will need to be modified to capture other image types
        // but for testing purposes it is good enough
        if (HttpContext.Current.Request.Path.EndsWith(".gif", StringComparison.OrdinalIgnoreCase))
        {
            // The version number will be generated but again for testing purposes this
            // is good enough
            var pathWithCacheBuster = string.Format("{0}?v1.0.0.0", HttpContext.Current.Request.Path);

            HttpContext.Current.RewritePath(pathWithCacheBuster);
        }
    }
}

I then registered the module in web.config like this 然后我像这样在web.config中注册了模块

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <add name="CacheBusterImageHandler" type="MyAssembly.CacheBusterImageHandler" preCondition="managedHandler" />
    ...

I then verified that the requests were getting processed by the module by using breakpoints, however when I checked in Firebug the image requests did not have the cache buster appended to URL. 然后,我使用断点验证了请求已由模块处理,但是当我在Firebug中检入图像请求时, 没有将缓存无效项附加到URL。 I then decided to read the documentation for the RewritePath method and found that of course it simply redirects the request but does not alter the requested URL. 然后,我决定阅读RewritePath方法的文档,并发现它当然只是重定向请求,但不会更改请求的URL。

Questions 问题

Is there a way in an HttpModule to append the cache buster to the query string? HttpModule中是否可以将高速缓存破坏程序附加到查询字符串?

If not, is there some other way I can achieve the same result without having to modify every reference to an image? 如果没有,是否有其他方法可以实现相同的结果而不必修改对图像的每个引用?

"Is there a way in an HttpModule to append the cache buster to the query string?" “ HttpModule中是否有一种方法可以将缓存破坏符附加到查询字符串?”

No. That is far to late in the process. 不。那是很晚的过程。 The URL has to be changed when you put it in the page, that's what the browser uses to check if the image is in the cache or not. 将URL放在页面中时必须更改URL,这是浏览器用来检查图像是否在缓存中的内容。

"If not, is there some other way I can achieve the same result without having to modify every reference to an image?" “如果没有,是否有其他方法可以实现相同的结果而不必修改对图像的每个引用?”

That depends on how you put the image URLs in the page, but there is no way of changingt he URLs that works for all way to put an URL in the page. 这取决于您将图像URL放置在页面中的方式,但是无法更改所有可用于在页面中放置URL的URL。

You can make a method that calculates the version number/string to include, and add that to all URLs. 您可以创建一个方法来计算要包括的版本号/字符串,并将其添加到所有URL。 That way you only have to make the change once, not every time an image changes. 这样,您只需要进行一次更改,而不必每次更改图像。

The method could use the version number or compile time of the assembly if you want to invalidate the cache every time that you deploy the page, or the update time of the image file. 如果您想在每次部署页面时使缓存无效或映像文件的更新时间,则该方法可以使用程序集的版本号或编译时间。

Basically: 基本上:

<img src="/images/logo.png<%= ImageVersion("/images/logo.png") %>" alt="Logo">

Using something like: 使用类似:

public static string ImageVersion(string name) {
  FileInfo info = new FileInfo(HttpContect.Current.MapPath(name));
  int time = (int)((info.LastWriteTimeUtc - new DateTime(2000,1,1)).TotalMinutes);
  return "?v=" + time.ToString();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM