Domanda

I have been migrating a .NET 2.0 web forms application to use .NET 3.5 and a new infrastructure. There is a GridView inside an UpdatePanel, with an Actions column which contains icons to perform an action for that row. A problem that I am having in IE 6 is that images are not caching. This is particularly noticeable on the Actions column because there are 9 icons x 100 rows = 900 icons to load. Internet Explorer counts down these images from 900 until they are all loaded.

This problem does not appear to be limited to the images inside the GridView which is inside an UpdatePanel because I can see header images being reloaded each time there is a page refresh.

I have done my research:

  • Anyone have ideas for solving the "n items remaining" problem on Internet Explorer? - this is a different problem.
  • Dear IE6: Please Cache my Images. - I did think that this would solve all of the problems, but no. I have tried setting the image as a background image inside a div but no success. I also tried putting all icons inside a User Control and including this before the GridView is loaded.
  • I have an old infrastructure (where this problem did not exist) to compare IIS configurations and they are exactly the same.
  • Using Fiddler I can frustratingly see each image being requested. The Cache Header is Cache-Control: private. Just noticed Date: Tue, 29 Mar 2011 07:35:53 GMT (which is an hour ago) in this Cache Header. Does that have anything to do with it?
  • This caching problem appears to be intermittent. I will load the page up for the first time and no images will be cached so ~1000 images will be independently loaded. I may refresh the page and images will be cached. If I delete all temporary files/offline content then the images will be loaded independently again.
  • At first I thought this only occurred when deploying the application to the new infrastructure (requests being made cross-forest) but it does happen on my local machine too when all images are local.
  • This is only a problem in IE 6!!!

Please let me know if I can provide other information.

UPDATE 1

Workarounds which have already been attempted with no success:

  • The handler solution proposed by @Afshin Gh. UPDATE 2 The code in the answer actually works. A different version must have been attempted previously.
  • The hidden images solution proposed by @Blue Steel.

UPDATE 2

Some of the other solutions may have worked here but I have gone with the code provided by @Afshin Gh.

È stato utile?

Soluzione

Use this handler:

Public NotInheritable Class ImageHandler
    Implements IHttpHandler

    Private Const REQUEST_KEY As String = "pic"

    Public ReadOnly Property IsReusable() As Boolean Implements System.Web.IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property

    Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest
        If Not String.IsNullOrEmpty(context.Request.QueryString(REQUEST_KEY)) Then
            Dim fileName As String = context.Request.QueryString(REQUEST_KEY)

            Try

                Dim fileInfo As New IO.FileInfo(context.Server.MapPath(fileName))

                If fileInfo.Exists Then
                    context.Response.Cache.SetCacheability(HttpCacheability.Public)
                    context.Response.Cache.SetExpires(Date.Now.AddYears(1))

                    Dim fileExt As String = fileInfo.Extension.Remove(0, 1).ToUpperInvariant

                    If fileExt = "JPG" Then
                        context.Response.ContentType = "image/jpeg"
                    Else
                        context.Response.ContentType = "image/" & fileExt
                    End If

                    context.Response.TransmitFile(fileInfo.FullName)

                End If

            Catch ex As Exception
            End Try

        End If
    End Sub

End Class

Register it in your web.config:

    <httpHandlers>
        <add verb="*" path="image.axd" type="MyApp.ImageHandler, MyApp" validate="false"/>
    </httpHandlers>

Use it like this:

<img src="image.axd?pic=/App_Themes/Modern/Logo.jpg" />

Altri suggerimenti

Does fiddler show cache control: private for other browsers as well? If so they won't be cached either. Are you using a custom control to serve up the images in the grid? If so you probably aren't handling the cache headers correctly (including 304 responses etc).

I suggest to set this cache parameters on header.

Response.Cache.AppendCacheExtension("post-check=900, pre-check=3600");

You can read more about here http://www.rdlt.com/cache-control-post-check-pre-check.html or google it.

Check it out and tell me if this solve your issue.

Have you tried adding the 9 images to the top of your page (outside the update panel) but set to hidden?

<asp:Image ID="Image1" ImageUrl = "images/img1.jpg" runat="server" style = "visibility:hidden" />
<asp:Image ID="Image2" ImageUrl = "images/img2.jpg" runat="server" style = "visibility:hidden" />
<asp:Image ID="Image3" ImageUrl = "images/img3.jpg" runat="server" style = "visibility:hidden" />
...
<asp:Image ID="Image9" ImageUrl = "images/img9.jpg" runat="server" style = "visibility:hidden" /> 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top